using UnityEngine;
using System.Collections.Generic;
using System.Linq;

public class SpriteToMesh : MonoBehaviour
{
    [Header("Sprite Settings")]
    public Sprite targetSprite;
    [Range(0.01f, 0.5f)] public float alphaThreshold = 0.1f;
    [Range(0.1f, 10f)] public float simplifyTolerance = 1.0f;

    [Header("Mesh Settings")]
    public Material meshMaterial;
    [Range(0.1f, 2f)] public float meshDepth = 0.1f;
    public bool generateBackface = true;

    [Header("Preview")]
    public bool showOutlineGizmo = true;
    public Color outlineColor = Color.green;

    private List<Vector2> _contourPoints = new List<Vector2>();
    private Mesh _generatedMesh;

    [ContextMenu("Convert Sprite to Mesh")]
    public void ConvertSpriteToMesh()
    {
        if (targetSprite == null)
        {
            Debug.LogError("Target sprite is not assigned!");
            return;
        }

        // 从精灵获取纹理
        Texture2D texture = GetTextureFromSprite(targetSprite);
        if (texture == null) return;

        // 提取轮廓点
        _contourPoints = GetContourPoints(texture, alphaThreshold);

        // 简化轮廓
        if (simplifyTolerance > 0.1f)
        {
            _contourPoints = SimplifyContour(_contourPoints, simplifyTolerance);
        }

        // 三角剖分
        _generatedMesh = TriangulateContour(_contourPoints, meshDepth, generateBackface);

        // 创建网格对象
        CreateMeshObject(_generatedMesh, targetSprite.name + "_Mesh", meshMaterial);
    }

    private Texture2D GetTextureFromSprite(Sprite sprite)
    {
        if (sprite.texture.isReadable)
        {
            return sprite.texture;
        }
        else
        {
            // 创建纹理的副本
            Texture2D newTexture = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height);
            Color[] pixels = sprite.texture.GetPixels(
                (int)sprite.rect.x,
                (int)sprite.rect.y,
                (int)sprite.rect.width,
                (int)sprite.rect.height);
            newTexture.SetPixels(pixels);
            newTexture.Apply();
            return newTexture;
        }
    }

    private List<Vector2> GetContourPoints(Texture2D texture, float alphaThreshold)
    {
        List<Vector2> points = new List<Vector2>();
        int width = texture.width;
        int height = texture.height;

        // 使用边界追踪算法获取轮廓
        bool[,] visited = new bool[width, height];

        // 找到第一个边界点
        Vector2Int startPoint = FindStartPoint(texture, alphaThreshold, visited);
        if (startPoint == Vector2Int.one * -1) return points;

        // 边界追踪
        Vector2Int current = startPoint;
        Vector2Int previous = new Vector2Int(-1, -1);
        int[,] directions = new int[,] { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } };

        do
        {
            points.Add(current);
            visited[current.x, current.y] = true;

            Vector2Int next = Vector2Int.one * -1;
            int startDir = (previous.x == -1) ? 0 : GetDirectionIndex(previous, current);

            // 检查8个邻接方向
            for (int i = 0; i < 8; i++)
            {
                int dirIndex = (startDir + i) % 8;
                Vector2Int neighbor = current + new Vector2Int(directions[dirIndex, 0], directions[dirIndex, 1]);

                if (IsValidPoint(neighbor, width, height) &&
                    !visited[neighbor.x, neighbor.y] &&
                    IsBoundaryPixel(texture, neighbor, alphaThreshold))
                {
                    next = neighbor;
                    break;
                }
            }

            previous = current;
            current = next;
        } while (current != startPoint && current != Vector2Int.one * -1);

        return points;
    }

    private Vector2Int FindStartPoint(Texture2D texture, float alphaThreshold, bool[,] visited)
    {
        for (int y = 0; y < texture.height; y++)
        {
            for (int x = 0; x < texture.width; x++)
            {
                if (IsBoundaryPixel(texture, new Vector2Int(x, y), alphaThreshold) && !visited[x, y])
                {
                    return new Vector2Int(x, y);
                }
            }
        }
        return Vector2Int.one * -1;
    }

    private bool IsBoundaryPixel(Texture2D texture, Vector2Int point, float alphaThreshold)
    {
        Color pixel = texture.GetPixel(point.x, point.y);
        if (pixel.a <= alphaThreshold) return false;

        // 检查8个相邻像素
        for (int dy = -1; dy <= 1; dy++)
        {
            for (int dx = -1; dx <= 1; dx++)
            {
                if (dx == 0 && dy == 0) continue;

                Vector2Int neighbor = point + new Vector2Int(dx, dy);
                if (IsValidPoint(neighbor, texture.width, texture.height))
                {
                    if (texture.GetPixel(neighbor.x, neighbor.y).a <= alphaThreshold)
                    {
                        return true;
                    }
                }
                else
                {
                    // 边界像素
                    return true;
                }
            }
        }
        return false;
    }

    private bool IsValidPoint(Vector2Int point, int width, int height)
    {
        return point.x >= 0 && point.x < width && point.y >= 0 && point.y < height;
    }

    private int GetDirectionIndex(Vector2Int from, Vector2Int to)
    {
        Vector2Int dir = to - from;
        if (dir == new Vector2Int(0, 1)) return 0;
        if (dir == new Vector2Int(1, 1)) return 1;
        if (dir == new Vector2Int(1, 0)) return 2;
        if (dir == new Vector2Int(1, -1)) return 3;
        if (dir == new Vector2Int(0, -1)) return 4;
        if (dir == new Vector2Int(-1, -1)) return 5;
        if (dir == new Vector2Int(-1, 0)) return 6;
        if (dir == new Vector2Int(-1, 1)) return 7;
        return 0;
    }

    private List<Vector2> SimplifyContour(List<Vector2> points, float tolerance)
    {
        if (points.Count < 3) return points;

        List<Vector2> simplified = new List<Vector2>();
        simplified.Add(points[0]);

        Vector2 lastAdded = points[0];
        for (int i = 1; i < points.Count - 1; i++)
        {
            if (Vector2.Distance(lastAdded, points[i]) > tolerance)
            {
                simplified.Add(points[i]);
                lastAdded = points[i];
            }
        }

        simplified.Add(points[points.Count - 1]);
        return simplified;
    }

    private Mesh TriangulateContour(List<Vector2> contour, float depth, bool generateBackface)
    {
        if (contour.Count < 3) return null;

        Mesh mesh = new Mesh();
        List<Vector3> vertices = new List<Vector3>();
        List<int> triangles = new List<int>();
        List<Vector2> uv = new List<Vector2>();

        // 计算中心点用于三角剖分
        Vector2 center = Vector2.zero;
        foreach (Vector2 point in contour)
        {
            center += point;
        }
        center /= contour.Count;

        // 添加正面顶点
        for (int i = 0; i < contour.Count; i++)
        {
            vertices.Add(new Vector3(contour[i].x, contour[i].y, -depth * 0.5f));
            uv.Add(new Vector2(contour[i].x / targetSprite.rect.width, contour[i].y / targetSprite.rect.height));
        }

        // 添加中心顶点
        int centerIndex = vertices.Count;
        vertices.Add(new Vector3(center.x, center.y, -depth * 0.5f));
        uv.Add(new Vector2(center.x / targetSprite.rect.width, center.y / targetSprite.rect.height));

        // 创建正面三角形
        for (int i = 0; i < contour.Count; i++)
        {
            int next = (i + 1) % contour.Count;
            triangles.Add(i);
            triangles.Add(next);
            triangles.Add(centerIndex);
        }

        // 添加背面顶点
        int backfaceStart = vertices.Count;
        for (int i = 0; i < contour.Count; i++)
        {
            vertices.Add(new Vector3(contour[i].x, contour[i].y, depth * 0.5f));
            uv.Add(new Vector2(contour[i].x / targetSprite.rect.width, contour[i].y / targetSprite.rect.height));
        }

        // 添加背面中心顶点
        int backCenterIndex = vertices.Count;
        vertices.Add(new Vector3(center.x, center.y, depth * 0.5f));
        uv.Add(new Vector2(center.x / targetSprite.rect.width, center.y / targetSprite.rect.height));

        // 创建背面三角形（如果需要）
        if (generateBackface)
        {
            for (int i = 0; i < contour.Count; i++)
            {
                int next = (i + 1) % contour.Count;
                triangles.Add(backfaceStart + next);
                triangles.Add(backfaceStart + i);
                triangles.Add(backCenterIndex);
            }
        }

        // 创建侧面（如果需要）
        if (depth > 0)
        {
            int sideStart = vertices.Count;
            for (int i = 0; i < contour.Count; i++)
            {
                vertices.Add(new Vector3(contour[i].x, contour[i].y, -depth * 0.5f));
                uv.Add(new Vector2(contour[i].x / targetSprite.rect.width, contour[i].y / targetSprite.rect.height));
                vertices.Add(new Vector3(contour[i].x, contour[i].y, depth * 0.5f));
                uv.Add(new Vector2(contour[i].x / targetSprite.rect.width, contour[i].y / targetSprite.rect.height));
            }

            for (int i = 0; i < contour.Count; i++)
            {
                int next = (i + 1) % contour.Count;

                // 第一个三角形
                triangles.Add(sideStart + i * 2);
                triangles.Add(sideStart + next * 2);
                triangles.Add(sideStart + i * 2 + 1);

                // 第二个三角形
                triangles.Add(sideStart + next * 2);
                triangles.Add(sideStart + next * 2 + 1);
                triangles.Add(sideStart + i * 2 + 1);
            }
        }

        mesh.vertices = vertices.ToArray();
        mesh.triangles = triangles.ToArray();
        mesh.uv = uv.ToArray();
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();

        return mesh;
    }

    private void CreateMeshObject(Mesh mesh, string name, Material material)
    {
        GameObject meshObject = new GameObject(name);
        MeshFilter filter = meshObject.AddComponent<MeshFilter>();
        MeshRenderer renderer = meshObject.AddComponent<MeshRenderer>();

        filter.mesh = mesh;
        renderer.material = material ? material : new Material(Shader.Find("Standard"));

        // 添加碰撞体
        MeshCollider collider = meshObject.AddComponent<MeshCollider>();
        collider.sharedMesh = mesh;
    }

    private void OnDrawGizmos()
    {
        if (!showOutlineGizmo || _contourPoints == null || _contourPoints.Count < 2) return;

        Gizmos.color = outlineColor;

        // 绘制轮廓
        for (int i = 0; i < _contourPoints.Count; i++)
        {
            int next = (i + 1) % _contourPoints.Count;
            Vector3 from = new Vector3(_contourPoints[i].x, _contourPoints[i].y, 0);
            Vector3 to = new Vector3(_contourPoints[next].x, _contourPoints[next].y, 0);
            Gizmos.DrawLine(from, to);
        }

        // 绘制轮廓点
        Gizmos.color = Color.red;
        foreach (Vector2 point in _contourPoints)
        {
            Gizmos.DrawSphere(new Vector3(point.x, point.y, 0), 0.5f);
        }
    }
}